package p2pcdnsim.xml;

import java.util.Iterator;

import org.jdom.Document;
import org.jdom.Element;

import p2pcdnsim.exception.LinkAlreadyInsertedException;
import p2pcdnsim.exception.NodeAlreadyInsertedException;
import p2pcdnsim.exception.NodeUnexistentException;
import p2pcdnsim.network.ApplicationLayer;
import p2pcdnsim.network.DropTail;
import p2pcdnsim.network.GenericAddress;
import p2pcdnsim.network.LANBus;
import p2pcdnsim.network.Link;
import p2pcdnsim.network.NetworkLayer;
import p2pcdnsim.network.NetworkTopologyBuilder;
import p2pcdnsim.network.Node;
import p2pcdnsim.network.RouterNode;
import p2pcdnsim.network.ShortestPathRouterTableBuilder;
import p2pcdnsim.network.TransportLayer;

import desmoj.core.simulator.SimTime;

public class XMLNetworkTopologyBuilder extends NetworkTopologyBuilder {
	private RouterXMLHandler routerXMLHandler;
	private String linkSpeed;
	private String delay;
	
	private int totalNodes;
	

	public XMLNetworkTopologyBuilder (Document doc, String linkSpeed, String delay, String queue) {
		routerXMLHandler = new RouterXMLHandler(doc, linkSpeed, delay, queue);
		this.linkSpeed = linkSpeed;
		this.delay = delay;
		this.totalNodes = routerXMLHandler.totalNodes();
	}

	@Override
	public void assignRouterTables() throws NodeUnexistentException {
        //Assign router tables
		ShortestPathRouterTableBuilder sp =  new ShortestPathRouterTableBuilder(topology);
		for(int i = 0; i < totalNodes; i++) {
			Node n = topology.getNode(i);
			System.out.println("      RouterTable: working on node "+n.getNodeId());
			n.getNetworkLayer().setRouterTable(sp.getRouterTable(i));
		}
	}

	@Override
	public void attributeNodeAddresses() throws NodeUnexistentException {
        //Attribute node addresses
		for(int i = 0; i < totalNodes; i++) {
			Node n = topology.getNode(i);
			n.getNetworkLayer().setNetworkAddress(new GenericAddress("AddressNode" + n.getNodeId()));
		}
	}

	@Override
	public void buildNetworkStack() throws NodeUnexistentException {
		for(int i = 0; i < totalNodes; i++) {
			Node n = topology.getNode(i);
			n.setNetworkLayer(new NetworkLayer(topology.getModel()));
			n.getNetworkLayer().setTransportLayer(new TransportLayer(topology.getModel()));
			n.getNetworkLayer().getTransportLayer().setApplicationLayer(new ApplicationLayer(topology.getModel()));
		}
	}

	@Override
	public void createLinks() throws NodeUnexistentException, LinkAlreadyInsertedException {
		Link link;
	
		Iterator<Element> i = routerXMLHandler.iterator();
		
		while (i.hasNext()) {
			Element linksTemp = i.next();
			int nodeTo    = Integer.parseInt(linksTemp.getChild("NodeTo").getText());
			int nodeFrom  = Integer.parseInt(linksTemp.getChild("NodeFrom").getText());
			int linkSpeed = Integer.parseInt(linksTemp.getChild("LinkSpeed").getText());
			//String queue  = linksTemp.getChild("Queue").getText();
			
			try {
				link = topology.createLink(topology.getModel(),nodeFrom,nodeTo,linkSpeed,new SimTime(0.0001), new DropTail());
				topology.addLink(link);
				//link.activate(new SimTime(0.0));
				
				link = topology.createLink(topology.getModel(),nodeTo,nodeFrom,linkSpeed,new SimTime(0.0001), new DropTail());
				topology.addLink(link);
				//link.activate(new SimTime(0.0));
			} catch (LinkAlreadyInsertedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void createNodes() throws NodeAlreadyInsertedException {
		for(int i = 0; i < totalNodes; i++) {
			RouterNode n = new RouterNode(i);
			topology.addNode(n);
		}
	}

	@Override
	public void createBus() throws NodeUnexistentException {
		for(int i=0; i < totalNodes; i++) {
			RouterNode node = topology.getNode(i);
			LANBus bus = new LANBus(topology.getModel(), node , Integer.parseInt(linkSpeed), new SimTime(Double.parseDouble(delay)));
			node.setLinkBus(bus);
		}
	}

}
